
module riscv_control(
    input  wire [4:0] op,       // op[6:2] (5-bit)
    input  wire [2:0] func3,    // func3 (3-bit)
    input  wire       func7,    // func7[5] (1-bit)
 
    output reg [2:0] ExtOP,    // 3-bit 扩展操作控制
    output reg       RegWr,    // 寄存器写使能
    output reg [2:0] Branch,   // 3-bit 分支类型
    output reg       MemToReg, // 内存数据到寄存器
    output reg       MemWr,    // 内存写使能
    output reg [2:0] MemOP,    // 3-bit 内存操作类型
    output reg       ALUAsrc,  // ALU A输入源选择
    output reg [1:0] ALUBsrc,  // 2-bit ALU B输入源选择
    output reg [3:0] ALUop     // 4-bit ALU操作码
);

    // 组合逻辑解码
    always @(*) begin
        // 默认值（避免锁存器）
        ExtOP    = 3'b000;
        RegWr    = 1'b0;
        Branch   = 3'b000;
        MemToReg = 1'b0;
        MemWr    = 1'b0;
        MemOP    = 3'b000;
        ALUAsrc  = 1'b0;
        ALUBsrc  = 2'b00;
        ALUop    = 4'b0000;

        // 根据 op、func3、func7 解码
        case (op)
            // LUI
            5'b01101: begin
                ExtOP    = 3'b001;
                RegWr    = 1'b1;
                ALUBsrc  = 2'b01;
                ALUop    = 4'b0011;
            end
            // AUIPC
            5'b00101: begin
                ExtOP    = 3'b001;
                RegWr    = 1'b1;
                ALUAsrc  = 1'b1;
                ALUBsrc  = 2'b01;
                ALUop    = 4'b0000;
            end
            // ADDI
            5'b00100: begin
                if (func3 == 3'b000) begin
                    RegWr    = 1'b1;
                    ALUBsrc  = 2'b01;
                    ALUop    = 4'b0000;
                end
                // SLTI
                else if (func3 == 3'b010) begin
                    RegWr    = 1'b1;
                    ALUBsrc  = 2'b01;
                    ALUop    = 4'b0010;
                end
                // SLTIU
                else if (func3 == 3'b011) begin
                    RegWr    = 1'b1;
                    ALUBsrc  = 2'b01;
                    ALUop    = 4'b1010;
                end
                // XORI
                else if (func3 == 3'b100) begin
                    RegWr    = 1'b1;
                    ALUBsrc  = 2'b01;
                    ALUop    = 4'b0100;
                end
                // ORI
                else if (func3 == 3'b110) begin
                    RegWr    = 1'b1;
                    ALUBsrc  = 2'b01;
                    ALUop    = 4'b0110;
                end
                // ANDI
                else if (func3 == 3'b111) begin
                    RegWr    = 1'b1;
                    ALUBsrc  = 2'b01;
                    ALUop    = 4'b0111;
                end
                // SLLI
                else if (func3 == 3'b001 && func7 == 1'b0) begin
                    RegWr    = 1'b1;
                    ALUBsrc  = 2'b01;
                    ALUop    = 4'b0001;
                end
                // SRLI / SRAI
                else if (func3 == 3'b101) begin
                    RegWr    = 1'b1;
                    ALUBsrc  = 2'b01;
                    ALUop    = (func7 == 1'b0) ? 4'b0101 : 4'b1101;
                end
            end
            // ADD / SUB
            5'b01100: begin
                if (func3 == 3'b000) begin
                    RegWr    = 1'b1;
                    ALUop    = (func7 == 1'b0) ? 4'b0000 : 4'b1000;
                end
                // SLL
                else if (func3 == 3'b001 && func7 == 1'b0) begin
                    RegWr    = 1'b1;
                    ALUop    = 4'b0001;
                end
                // SLT
                else if (func3 == 3'b010 && func7 == 1'b0) begin
                    RegWr    = 1'b1;
                    ALUop    = 4'b0010;
                end
                // SLTU
                else if (func3 == 3'b011 && func7 == 1'b0) begin
                    RegWr    = 1'b1;
                    ALUop    = 4'b1010;
                end
                // XOR
                else if (func3 == 3'b100 && func7 == 1'b0) begin
                    RegWr    = 1'b1;
                    ALUop    = 4'b0100;
                end
                // SRL / SRA
                else if (func3 == 3'b101) begin
                    RegWr    = 1'b1;
                    ALUop    = (func7 == 1'b0) ? 4'b0101 : 4'b1101;
                end
                // OR
                else if (func3 == 3'b110 && func7 == 1'b0) begin
                    RegWr    = 1'b1;
                    ALUop    = 4'b0110;
                end
                // AND
                else if (func3 == 3'b111 && func7 == 1'b0) begin
                    RegWr    = 1'b1;
                    ALUop    = 4'b0111;
                end
            end
            // JAL
            5'b11011: begin
                ExtOP    = 3'b100;
                RegWr    = 1'b1;
                Branch   = 3'b001;
	        ALUAsrc  = 1'b1;
                ALUBsrc  = 2'b10;
            end
            // JALR
            5'b11001: begin
                if (func3 == 3'b000) begin
                    RegWr    = 1'b1;
                    Branch   = 3'b010;
                    ALUAsrc  = 1'b1;
                    ALUBsrc  = 2'b10;
                end
            end
            // BEQ / BNE / BLT / BGE / BLTU / BGEU
            5'b11000: begin
                ExtOP    = 3'b011;
                ALUop    = (func3[2:1] == 2'b11) ? 4'b1010 : 4'b0010;  // SLT or SLTU
                case (func3) 
                    3'b000: begin
                         Branch = 3'b100;
                    end
                    3'b001:begin
                         Branch = 3'b101;
                    end
                    3'b100:begin
                         Branch = 3'b110;
                    end
                    3'b101:begin
                         Branch = 3'b111;
                    end
                    3'b110:begin
                         Branch = 3'b110;
                    end
                    3'b111: begin
                         Branch = 3'b111;
                    end
                endcase
            end
            // LB / LH / LW / LBU / LHU
            5'b00000: begin
                RegWr    = 1'b1;
                MemToReg = 1'b1;
                MemOP    = func3;          // MemOP = func3
                ALUBsrc  = 2'b01;
            end
            // SB / SH / SW
            5'b01000: begin
                ExtOP    = 3'b010;
                MemWr    = 1'b1;
                MemOP    = func3;          // MemOP = func3
                ALUBsrc  = 2'b01;
            end
        endcase
    end

endmodule

